package com.road.yishi.admincmd;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.UnsupportedEncodingException;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Iterator;
import java.util.List;
import java.util.Timer;
import java.util.TimerTask;
import java.util.Vector;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.road.common.core.NetConfigXml;

public class AdminCmdMgr extends Thread {

	private final static Logger LOG = LoggerFactory.getLogger(AdminCmdMgr.class);

	// 线程存活时间1分钟
	private static final int keepLivingTime = 1000 * 60 * 3;
	private static final int scanTime = 1000;
	private static final String password = "123456";

	private int id;
	private List<Requestor> requestors;
	private ServerSocket serverSocket;
	private boolean isRunning;
	private Timer timer;
	private NetConfigXml netConfigXml;

	public AdminCmdMgr(NetConfigXml netConfigXml, String packageName) {
		super("Thread-AdminCmdMgr-" + netConfigXml.getAdminPort());
		try {
			this.netConfigXml = netConfigXml;
			this.id = 0;
			this.serverSocket = new ServerSocket(netConfigXml.getAdminPort());
			this.isRunning = true;
			RequestMapping.init(packageName);
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	@Override
	public void run() {
		LOG.info("开启后台管理命令成功,端口： {},会话存活时间 ：{}，扫描间隔时间{}", netConfigXml.getAdminPort(), keepLivingTime, scanTime);
		try {
			while (isRunning) {
				Socket socket = serverSocket.accept();
				if (requestors == null) {
					requestors = new Vector<Requestor>();
				}
				id++;
				Requestor requestor = new Requestor(socket, id);
				requestors.add(requestor);
				requestor.start();

				/**
				 * 每秒检查空闲线程，如果空闲时间》keepLivingTime，则把当前线程停掉
				 */
				timer = new Timer();
				timer.schedule(new TimerTask() {

					@Override
					public void run() {
						System.out.println("当前线程个数:" + id);

						if (id > 0) {
							Iterator<Requestor> iterator = requestors.iterator();
							try {
								while (iterator.hasNext()) {
									AdminCmdMgr.Requestor requestor = (AdminCmdMgr.Requestor) iterator.next();
									long idleTime = System.currentTimeMillis() - requestor.getLastRunTime();

									System.out.println("线程： " + requestor.getName() + ",空闲时间: " + idleTime);

									if (idleTime > keepLivingTime) {
										requestor.stopRequestor();
										requestor.stopping();
										iterator.remove();
										id--;
									}
								}
							} catch (IOException e) {
								e.printStackTrace();
							}
						} else {
							cancel();
							timer.cancel();
						}
					}
				}, 0, scanTime);

			}
		} catch (IOException e) {
		}
	}

	public void stopping() {
		try {
			isRunning = false;
			if (requestors != null) {
				for (Requestor requestor : requestors) {
					requestor.stopping();
				}
			}
			serverSocket.close();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	class Requestor extends Thread {

		private Socket socket;
		private BufferedReader reader;
		private BufferedWriter writer;
		private boolean isSafe;

		// 当前线程
		private Thread currentThread;
		// 当前线程最后运行时间
		private long lastRunTime;
		// 是否停止当前线程
		private volatile boolean stopRequested;

		public Requestor(Socket socket, int id) throws UnsupportedEncodingException, IOException {
			super("Admin-Request-Client-" + id);
			this.currentThread = Thread.currentThread();
			this.socket = socket;
			this.isSafe = false;
			this.stopRequested = false;
			reader = new BufferedReader(new InputStreamReader(socket.getInputStream(), "UTF-8"));
			writer = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream(), "UTF-8"));

			this.lastRunTime = System.currentTimeMillis();
		}

		public void run() {
			try {
				send("connect successfully, welcome admin... type quit or exit to exit");
				String line;
				while ((line = reader.readLine()) != null && !stopRequested) {
					this.lastRunTime = System.currentTimeMillis();
					if (!isSafe) {
						if (line.contains(password)) {
							isSafe = true;
							send("congratulations to pass judge... ");
						} else {
							send("please enter password to contion... ");
						}
					}
					if (isSafe) {
						String[] params = line.split(" ");
						AdminCommand adminCommand = RequestMapping.getAdmincmdByPath(params[0]);
						if (adminCommand != null) {
							adminCommand.execute(params, writer);
						} else {
							send("command not found, you can use help list all command.");
						}
					}
				}
			} catch (IOException e) {
				try {
					socket.close();
				} catch (IOException e1) {
					e1.printStackTrace();
				}
			}
		}

		public void send(String str) throws IOException {
			writer.write(str);
			writer.newLine();
			writer.flush();
		}

		public void stopping() throws IOException {
			socket.close();
		}

		/**
		 * 停止当前线程
		 */
		public void stopRequestor() {
			this.stopRequested = true;
			if (currentThread != null) {
				currentThread.interrupt();
			}
		}

		public long getLastRunTime() {
			return lastRunTime;
		}

	}
}
